#include<stdio.h>
#include<stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include<unistd.h>
#include<assert.h>
#include<string.h>
#define Num 3
typedef void (*func_t)();   //函数指针
func_t handlerTask[Num];

//创建三个子任务
void func1()
{
  printf("call func1\n");
}

void func3()
{
  printf("call func3\n");
}

void func2()
{
  printf("call func2\n");
}

void handerTask()
{
  memset(handlerTask,0,sizeof(handlerTask));
  handlerTask[0]=func1;    //将函数指针与对应的函数相互链接
  handlerTask[1]=func2;
  handlerTask[2]=func3;
}

int main()
{
  pid_t id = fork();
  assert(id!=-1);
  if(id==0)
  {
    //child
    int cnt=50;
    while(cnt--)
    {
      printf("this child process pid:%d  cnt:%d \n",getpid(),cnt);
      sleep(1);
    }
    //野指针问题
    //int *p=NULL;
    //*p=100;
    exit(10);//进程退出
  } 

  //parent
  handerTask();
  int status=0;

  //设置waitpid最后一个参数为WNOHANG 是非阻塞的,这时候需要伦询
  while(1)
  {
    int ret=waitpid(id,&status,WNOHANG);
    if(ret==0)
    {
      //子进程调用成功&&子进程没退出
      //子进程没有退出，我的waitpid没有等待失败，仅仅是检测到了子进程没有退出
      printf("wait done ,but child is running\n");
      for(int i=0;handlerTask[i];++i)
      {
        handlerTask[i]();
      }
    }
    else if(ret>0)
    {
      //waitpid调用成功 && 子进程退出了
      printf("wait success  exit code: %d   sigal: %d\n",(status>>8)&0xff,status&0x7f);
      break;
    }
    else 
    {
      //waitpid调用失败
      printf("waitpid call failed\n");
      break;
    }
    sleep(1);

  }



  //下面采用的是阻塞等待
 /* //1、wait可以让操作系统释放子进程的僵尸状态
  //2、获取子进程的退出结果
  //在等待期间，如果子进程没有退出，父进程只有阻塞等待
  int ret = waitpid(id,&status,0); //第三个参数为0的时候为阻塞等待
  if(ret>0)
  {
    //如果想不想用status去表示，可以采用系统提供的宏
    //是否正常退出
    if(WIFEXITED(status))
    {
      //判断子进程运行结果是否OK
      printf("exit code: %d\n",WEXITSTATUS(status));
    }
    else 
    {
      printf("exit no normal!!!\n");
      
    }
    //printf("wait success  exit code: %d   sigal: %d\n",(status>>8)&0xff,status&0x7f);
  }
  */
  return 0;
}

